package com.hm.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HttpUtil {
	public static Logger logger = LoggerFactory.getLogger(HttpUtil.class);
	public static final int cache = 10 * 1024;
	public static final boolean isWindows;
	public static final String splash;
	public static final String root;
	static {
		if (System.getProperty("os.name") != null && 
			System.getProperty("os.name").toLowerCase().contains("windows")) {
			isWindows = true;
			splash = "\\";
			root = "C:";
		} else {
			isWindows = false;
			splash = "/";
			root = "/search";
		}
	}

	/**
	 * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
	 * @throws Exception 
	 */
	public static CloseableHttpResponse post(CloseableHttpClient httpClient, String url, Map<String, String> params) throws Exception {
		// 创建httpPost  
		HttpPost httpPost = null;
		CloseableHttpResponse response = null;
		
		// 创建参数队列  
		List<NameValuePair> formParams = new ArrayList<NameValuePair>();
		for(Iterator<String> iter = params.keySet().iterator(); iter.hasNext(); ){
			String key = iter.next();
			String value = params.get(key);
			formParams.add(new BasicNameValuePair(key, value));
		}
		UrlEncodedFormEntity uefEntity;
		try {
			uefEntity = new UrlEncodedFormEntity(formParams, "UTF-8");
			httpPost = new HttpPost(url);
			httpPost.setEntity(uefEntity);
			logger.info("executing request " + httpPost.getURI());
			response = httpClient.execute(httpPost);
			/*entity = response.getEntity();
			if (entity != null) {
				logger.info("--------------------------------------");
				logger.info("Response content: " + EntityUtils.toString(entity, "UTF-8"));
				logger.info("--------------------------------------");
			}*/
		} catch (Exception e) {
			logger.info("----------------post请求异常--------------------");
			e.printStackTrace();
			throw new Exception("post请求异常");
		} 
		return response;
	}

	/**
	 * 发送 get请求
	 * @throws Exception 
	 */
	public static CloseableHttpResponse get(CloseableHttpClient httpClient, String url) throws Exception {
		HttpGet httpGet = null;
		CloseableHttpResponse response = null;
		try {
			// 创建httpget.  
			httpGet = new HttpGet(url);
			logger.info("executing request " + httpGet.getURI());
			// 执行get请求.  
			response = httpClient.execute(httpGet);
			
			/*// 获取响应实体  
			entity = response.getEntity();
			logger.info("--------------------------------------");
			// 打印响应状态  
			logger.info(response.getStatusLine().toString());
			if (entity != null) {
				// 打印响应内容长度  
				logger.info("Response content length: " + entity.getContentLength());
				// 打印响应内容  
				logger.info("Response content: " + EntityUtils.toString(entity));
			}
			logger.info("------------------------------------");
			logger.info(entity.getContentType().toString());*/
		} catch (Exception e) {
			logger.info("----------------get请求异常--------------------");
			e.printStackTrace();
			throw new Exception("get请求异常");
		}
		return response;
	}


	/**
	 * 根据url下载文件，文件名从response header头中获取
	 * 
	 * @param url
	 * @return
	 * @throws Exception 
	 */
	public static void download(String url) throws Exception {
		download(null, url, null);
	}

	/**
	 * 根据url下载文件，文件名从response header头中获取
	 * 
	 * @param url
	 * @return
	 * @throws Exception 
	 */
	public static void download(CloseableHttpClient httpClient, String url) throws Exception {
		download(httpClient, url, null);
	}
	/**
	 * 根据url下载文件，保存到filepath中
	 * 
	 * @param url
	 * @param filePath
	 * @return
	 * @throws Exception 
	 */
	public static void download(CloseableHttpClient httpClient, String url, String filePath) throws Exception {
		try {
			HttpGet httpGet = new HttpGet(url);
			HttpResponse response = httpClient.execute(httpGet);

			HttpEntity entity = response.getEntity();
			InputStream is = entity.getContent();
			if (filePath == null)
				filePath = getFilePath(response);
			File file = new File(filePath);
			if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
				logger.error("系统异常，HttpUtil.download > Can not create the directory for file : {}", file.getAbsolutePath());
				throw new RuntimeException("系统异常，Can not create the directory for file : " + file.getAbsolutePath());
			}
			FileOutputStream fileout = new FileOutputStream(file);
			/**
			 * 根据实际运行效果 设置缓冲区大小
			 */
			byte[] buffer = new byte[cache];
			int ch = 0;
			while ((ch = is.read(buffer)) != -1) {
				fileout.write(buffer, 0, ch);
			}
			fileout.flush();
			fileout.close();
			is.close();

		} catch (Exception e) {
			e.printStackTrace();
			logger.info("下载版本文件失败");
			throw new Exception("下载版本文件失败");
		}
	}

	/**
	 * 获取response要下载的文件的默认路径
	 * 
	 * @param response
	 * @return
	 * @throws Exception 
	 */
	public static String getFilePath(HttpResponse response) throws Exception {
		String filePath = root + splash;
		String fileName = getFileName(response);

		if (fileName != null) {
			filePath += fileName;
		} else {
			logger.info("获取文件路径异常");
			throw new Exception("获取文件路径异常");
		}
		return filePath;
	}

	/**
	 * 获取response header中Content-Disposition中的filename值
	 * 
	 * @param response
	 * @return
	 * @throws Exception 
	 */
	public static String getFileName(HttpResponse response) throws Exception {
		Header contentHeader = response.getFirstHeader("Content-Disposition");
		String fileName = null;
		if (contentHeader != null) {
			HeaderElement[] values = contentHeader.getElements();
			if (values.length == 1) {
				NameValuePair param = values[0].getParameterByName("filename");
				if (param != null) {
					try {
						// filename = new String(param.getValue().toString().getBytes(), "utf-8");
						// filename = URLDecoder.decode(param.getValue(), "utf-8");
						fileName = param.getValue();
						logger.info("下载文件名称 > " + fileName);
					} catch (Exception e) {
						e.printStackTrace();
						logger.info("获取下载文件名称异常");
						throw new Exception("获取下载文件名称异常");
					}
				}
			}
		}
		return fileName;
	}

	
	
	/**
	 * HttpClient连接SSL
	 */
	public void ssl() {
		CloseableHttpClient httpclient = null;
		try {
			KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
			FileInputStream instream = new FileInputStream(new File("d:\\tomcat.keystore"));
			try {
				// 加载keyStore d:\\tomcat.keystore  
				trustStore.load(instream, "123456".toCharArray());
			} catch (CertificateException e) {
				e.printStackTrace();
			} finally {
				try {
					instream.close();
				} catch (Exception ignore) {
				}
			}
			// 相信自己的CA和所有自签名的证书
			SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();
			// 只允许使用TLSv1协议
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,
					SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
			// 创建http请求(get方式)
			HttpGet httpget = new HttpGet("https://localhost:8443/myDemo/Ajax/serivceJ.action");
			logger.info("executing request" + httpget.getRequestLine());
			CloseableHttpResponse response = httpclient.execute(httpget);
			try {
				HttpEntity entity = response.getEntity();
				logger.info("----------------------------------------");
				logger.info(response.getStatusLine().toString());
				if (entity != null) {
					logger.info("Response content length: " + entity.getContentLength());
					logger.info(EntityUtils.toString(entity));
					EntityUtils.consume(entity);
				}
			} finally {
				response.close();
			}
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} finally {
			if (httpclient != null) {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public void close(){
		
	}
}